//不需要文件路径，内存级，所以叫匿名，
//0，1，2分别是stdin，stdout，stderr，而3，4就是匿名管道的读端和写端
#include <unistd.h>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdio>
#include <string.h>

void childwrite(int wfd)
{
    char buffer[1024];
    int cnt = 0;
    while(1)
    {
        snprintf(buffer, sizeof(buffer), 
        "I am a child, mypid is %d, cnt is %d\n", 
        getpid(), cnt++);
        write(wfd, buffer, strlen(buffer));
        //当写的慢，读的快的时候，读就进入阻塞状态，是进程在阻塞 
        sleep(1); 
    }
}

void fatherread(int rfd)
{
    //管道容量是由上限的，当写的很快读的很慢的时候，就一次性把缓冲区读完
    char buffer[1024 * 4];
    while(1)
    {
        //读到就返回没有读到就进入堵塞状态，等下次写成功再读
        size_t n = read(rfd, buffer, sizeof(buffer) - 1);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cout << "child say:" << buffer << std::endl;
        }
        else if(n = 0){
            std::cout << "file end" << std::endl;
            break;
        }
    }
}

int main()
{
    std::cout << "vscode" << std::endl;
    int fds[2] = {0};
    int n = pipe(fds);
    if(n < 0)
    {
        std::cerr << "pipe error";
        return 1;
    }
    std::cout << "fd[0]" << fds[0] << std::endl;//3
    std::cout << "fd[1]" << fds[1] << std::endl;//4

    //创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        //子进程
        close(fds[0]);
        childwrite(fds[1]);
        close(fds[1]);
        exit(1);
    }
    close(fds[1]);
    fatherread(fds[0]);

    int status;
    int ret = waitpid(id, &status, 0);
    close(fds[0]);
    printf("exit code: %d, exit signal:%d\n", (status >> 8) & 0xFF, status & 0x7F);
    //获取进程退出码和进程退出信号：
    //传过去一个int，用来存储信号，后16位为信息
    //正常退出时，前八位为退出码，后八位未用
    //遇到异常退出或被杀死时，前八位未用，后八位中第一位为core dump信号，后七位
    //为退出信号

    return 0;
}

